#pragma once
#include "float.h"

class Memory{
public:
	static float* distance;
	static int* parent;
	static bool* visited;

	static float defaultDistance;
	static int defaultParent;
	static bool defaultVisited;

	static int* ticketCheck;
	static int ticketCheckSize;
	static int ticketNumber;

	static int size;

	class Context {
	public:
		float* distance = nullptr;
		int* parent = nullptr;
		bool* visited = nullptr;
		float defaultDistance;
		int defaultParent;
		bool defaultVisited;
		int* ticketCheck = nullptr;
		int ticketNumber;
		int size;

		Context(){};
	};

	static void loadContext(Context context) {
		distance = context.distance;
		parent = context.parent;
		visited = context.visited;
		defaultDistance = context.defaultDistance;
		defaultParent = context.defaultParent;
		defaultVisited = context.defaultVisited;
		ticketCheck = context.ticketCheck;
		ticketNumber = context.ticketNumber;
		size = context.size;
	}

	static void saveContext(Context context) {
		context.distance =distance;
		context.parent = parent;
		context.visited = visited;
		context.defaultDistance = defaultDistance;
		context.defaultParent = defaultParent;
		context.defaultVisited = defaultVisited;
		context.ticketCheck =ticketCheck;
		context.ticketNumber =ticketNumber;
		context.size =size;
	}

	static int initialise(int size, float defaultDistance, int defaultParent, bool defaultVisited) {
		defaultDistance = defaultDistance;
		defaultParent = defaultParent;
		defaultVisited = defaultVisited;
		size = size;

		if (ticketCheck == nullptr || ticketCheckSize != size) {
			if (ticketCheck)
			{
				delete[]ticketCheck;
			}
			ticketCheckSize = size;
			//System.out.println("REINITIALISE MEMORY " + size);
			distance = new float[size];
			for (size_t i = 0; i < size; i++)
			{
				distance[i] = FLT_MAX;
			}
			parent = new int[size];
			for (size_t i = 0; i < size; i++)
			{
				parent[i] = -1;
			}
			visited = new bool[size];
			for (size_t i = 0; i < size; i++)
			{
				visited[i] = false;
			}
			ticketCheck = new int[size];
			for (size_t i = 0; i < size; i++)
			{
				ticketCheck[i] = 1;
			}
			ticketNumber = 1;
		}
		else if (ticketNumber == -1) {
			ticketCheck = new int[size];
			ticketNumber = 1;
		}
		else {
			ticketNumber++;
		}

		return ticketNumber;
	}

	static int currentTicket() {
		return ticketNumber;
	}

	static int Getsize() {
		return size;
	}

	static float Getdistance(int index) {
		if (ticketCheck[index] != ticketNumber) return defaultDistance;
		return distance[index];
	}

	static int Getparent(int index) {
		if (ticketCheck[index] != ticketNumber) return defaultParent;
		return parent[index];
	}

	static bool Getvisited(int index) {
		if (ticketCheck[index] != ticketNumber) return defaultVisited;
		return visited[index];
	}

	static void setDistance(int index, float value) {
		if (ticketCheck[index] != ticketNumber) {
			distance[index] = value;
			parent[index] = defaultParent;
			visited[index] = defaultVisited;
			ticketCheck[index] = ticketNumber;
		}
		else {
			distance[index] = value;
		}
	}

	static void setParent(int index, int value) {
		if (ticketCheck[index] != ticketNumber) {
			distance[index] = defaultDistance;
			parent[index] = value;
			visited[index] = defaultVisited;
			ticketCheck[index] = ticketNumber;
		}
		else {
			parent[index] = value;
		}
	}

	static void setVisited(int index, bool value) {
		if (ticketCheck[index] != ticketNumber) {
			distance[index] = defaultDistance;
			parent[index] = defaultParent;
			visited[index] = value;
			ticketCheck[index] = ticketNumber;
		}
		else {
			visited[index] = value;
		}
	}

	static void clearMemory() {
		if (distance)
		{
			delete[]distance;
			distance = nullptr;
		}
		if (parent)
		{
			delete[]parent;
			parent = nullptr;
		}
		if (visited)
		{
			delete[]visited;
			visited = nullptr;
		}
		if (ticketCheck)
		{
			delete[]ticketCheck;
			ticketCheck = nullptr;
		}
		//System.gc();
	}
};
